package cn.whb.hrm.config;

import cn.whb.hrm.authen.MyAuthenFailHandler;
import cn.whb.hrm.authen.MyAuthenSuccessHandler;
import cn.whb.hrm.author.MyAuthorDeniedHandler;
import cn.whb.hrm.mapper.PermissionMapper;
import cn.whb.hrm.service.MyUserDetail;
import cn.whb.hrm.smslogin.SmsLoginFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity  //开启springsecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private DataSource dataSource;
   /* @Override
    @Bean
    protected UserDetailsService userDetailsService() {
        User user = new User("wang", "1", new ArrayList<>());
        InMemoryUserDetailsManager inMemoryUserDetailsManager = new InMemoryUserDetailsManager(user);
        return inMemoryUserDetailsManager;
    }*/

    /**
     * token存储方案设计
     * @return
     */
    @Bean
    public PersistentTokenRepository tokenStore(){
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        //repository.setCreateTableOnStartup(true);
        repository.setDataSource(dataSource);
        return repository;
    }

    @Bean
    public PasswordEncoder getEncoder(){
        return new BCryptPasswordEncoder();
    }

    public static void main(String[] args) {
        String pwd = "1";
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        System.out.println(encoder.encode(pwd));
    }

    /*@Override
    protected void configure(HttpSecurity http) throws Exception {
        //查出所有权限，
        List<Permission> permissions = permissionMapper.selectList(null);
        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry expressionInterceptUrlRegistry = http.authorizeRequests();
        //告诉spring什么样的资源需要什么权限
        permissions.stream().forEach(permission -> {
            expressionInterceptUrlRegistry.antMatchers(permission.getResource()).hasAuthority(permission.getSn());
        });
       //所有请求都需要权限
        expressionInterceptUrlRegistry.antMatchers("/login").permitAll() //登录请求放行
                .antMatchers("/login.html").permitAll() //登录页面放行
                .anyRequest().authenticated() //其他请求需要经过认证之后才能访问
                .and().formLogin()  //允许表单提交
                //.successForwardUrl("/test/success") //登陆成功之后访问的页面
                .successHandler(new MyAuthenSuccessHandler())  //自定义登录成功后的信息
                .failureHandler(new MyAuthenFailHandler())      //自定义登录失败后的信息
                .loginPage("/login.html")  //指定自定义的登录页面
                .loginProcessingUrl("/login")  //指定登录处理的url
                .and().logout().permitAll()  //允许登出
                .and().csrf().disable();   //不允许跨站访问
    }*/

    @Autowired
    private MyUserDetail myUserDetail;

    @Autowired
    private SmsAuthConfig smsAuthConfig;
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       //所有请求都需要权限
        http.authorizeRequests().antMatchers(HttpMethod.POST,"/login","/sms/send/*","/smslogin").permitAll() //登录请求放行
                .antMatchers("/login.html").permitAll() //登录页面放行
                .anyRequest().authenticated() //其他请求需要经过认证之后才能访问
                .and().formLogin()  //允许表单提交
                //.successForwardUrl("/test/success") //登陆成功之后访问的页面
                .successHandler(new MyAuthenSuccessHandler())  //自定义登录成功后的信息
                .failureHandler(new MyAuthenFailHandler())      //自定义登录失败后的信息
                .loginPage("/login.html")  //指定自定义的登录页面
                .loginProcessingUrl("/login")  //指定登录处理的url
                .and().logout().permitAll()  //允许登出
                .and().csrf().disable();   //不允许跨站访问
        //定义没有权限返回的结果
        http.exceptionHandling().accessDeniedHandler(new MyAuthorDeniedHandler());
        //配置token过期时间、存储方式、以及那个用户的token
        http.rememberMe()
                .tokenRepository(tokenStore())
                .userDetailsService(myUserDetail)
                .tokenValiditySeconds(3600);
        SmsLoginFilter smsLoginFilter = new SmsLoginFilter();
        //添加验证码检查的filter
        http.addFilterBefore(smsLoginFilter,UsernamePasswordAuthenticationFilter.class);

        //添加短信验证的配置
        http.apply(smsAuthConfig);
    }
}
